#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>

// 测宽、测错角算法实现

// 两条物料产生了偏差，需要使用算法检测出左右差了多少，宽度是多少
/*
直裁物料产生的差
		|—————|
		|     |
		|     |
		|     |
		|	  |
	|—————|	  |
	|     |———|
	|     |
	|     |
	|     |
	|     |
	|—————|

	斜裁物料产生的差
	|\
	| \
	|  \
	|	\
	|    |
	|    |
	|    |
	\    |
	|\   |
	| \  |
	|  \ |
	|   \|
	|    \
	|    |
	\    |
	 \   |
	  \  |
	   \ |
		\|

*/

/**
 * @brief 准备测量数据
 * @param data
 * @param len
 */
static void PrepareData(uint16_t data[][2], uint16_t len)
{
	if (data == NULL || len == 0)
	{
		printf("No data is ready\n");
		return;
	}

	uint16_t RandData[10][2] = {0};

	for (uint16_t i = 0; i < 10; i++)
	{
		RandData[i][0] = (uint16_t)(rand() % 100);
		RandData[i][1] = RandData[i][0] + (uint16_t)(rand() % 50);
	}

	for (uint16_t i = 0; i < len; i++)
	{
		data[i][0] = RandData[i / 10][0];
		data[i][1] = RandData[i / 10][1];
	}

	for (uint16_t i = 0; i < len; i++)
	{
		printf("[%d, %d]\n", data[i][0], data[i][1]);
	}
}

static void InsertData(uint16_t data[], uint16_t len, uint16_t num)
{
	if (len == 0 || data == NULL || num == 0)
	{
		return;
	}

	uint16_t index = 0, flag = 0;

	// 找到要插入的位置,并且唯一值
	for (uint16_t i = 0; i < len; i++)
	{
		if (data[i] == 0)
		{
			index = i;
			break;
		}

		if (data[i] == num)
		{
			flag = 1;
			break;
		}
	}

	if (flag == 1)
	{
		return;
	}

	printf("insert index: %d num: %d\n", index, num);

	// 插入新值
	data[index] = num;
}

/**
 * @brief 测宽
 * @param data
 * @param len
 */
static int MeasureWidth(uint16_t data[][2], uint16_t len)
{
	if (data == NULL || len == 0)
	{
		printf("No data to measure\n");
		return -1;
	}

	uint16_t DiffWidth[100] = {0};

	// 找出差值
	for (uint16_t i = 0; i < len - 1; i++)
	{
		uint16_t Diff = data[i][1] - data[i][0];
		InsertData(DiffWidth, len - 1, Diff);
	}

	for (uint16_t i = 0; i < len - 1; i++)
	{
		if (DiffWidth[i] != 0)
		{
			printf("%d ", DiffWidth[i]);
		}
	}
}

/// @brief 查找左侧宽度
/// @param DiffWidth
/// @param len
static void FindLeftWidth(uint16_t DiffWidth[], uint16_t len)
{
	if (DiffWidth == NULL || len == 0)
	{
		printf("Find Left width fail\n");
		return;
	}

	uint16_t Num[100] = {0};
	for (uint16_t i = 0; i < len; i++)
	{
	}
}

typedef struct
{
	uint16_t SystemTatus; // 系统状态
	uint16_t QoR;		  // 检测质量
	uint16_t OID;		  // 外径宽度
	uint16_t FBB;		  // 距离线缆接头处物料首次遮挡的距离
	uint16_t LBB;		  // 距离线缆接头处物料结束遮挡的距离

} Sick_MLG2_Data_t;

Sick_MLG2_Data_t SickMLG2_Data = {0};

static int FindStrIndex(const char *Str1, char Str2)
{
	if (Str1 == NULL)
	{
		return -1;
	}

	for (uint16_t i = 0; i < 20; i++)
	{
		if (Str1[i] == Str2)
		{
			return i;
		}
	}

	return -1;
}

typedef struct
{
	uint16_t LeftWidth;
	uint16_t RightWidth;
	uint16_t LeftOffsetCount;	  // 左侧遮挡次数
	uint16_t RightOffsetCount;	  // 右侧遮挡次数
	uint16_t LeftExceptionCount;  // 左侧异常次数
	uint16_t RightExceptionCount; // 右侧异常次数

} Diff_t;

Diff_t Diff = {0};

/// @brief  差值计算
/// @param data
/// @param len
void Diff_Calc(uint16_t *data, uint16_t len, Diff_t *Result)
{

	int32_t v = 0;
	for (uint16_t i = 0, j = len - 1; i < len; i++, j--)
	{
		// printf("%d - %d  = %d - %d\n", i, j, data[i] - data[j]);
		// continue;
		v = data[i] - data[j];
		if (v)
		{
			Result->LeftOffsetCount++;
			Result->LeftWidth += v;
			Result->LeftExceptionCount++;
		}
		else
		{
			if (v == 0)
			{
				continue;
			}

			Result->RightOffsetCount++;
			Result->RightWidth += v;
			Result->RightExceptionCount++;
		}
	}

	// 平均值计算
	if (Result->LeftExceptionCount)
	{
		Result->LeftWidth = Result->LeftWidth / Result->LeftExceptionCount;
	}

	if (Result->RightExceptionCount)
	{
		Result->RightWidth = Result->RightWidth / Result->RightExceptionCount;
	}
}

void BufPrint(uint16_t *Buf, uint16_t Len)
{
	for (uint16_t i = 0; i < Len; i++)
	{
		printf("%d ", Buf[i]);
	}

	printf("\n");
}

static uint16_t CacheBuf[300] = {0},
				CacheIndex = 0,
				CacheSize = 0;

/// @brief 错边检测算法1,尝试使用上下边缘求差的方式实现,如果存在一个错角,那应该会产生一个巨大差值,以此来判定存在一个错角
/// @param argc
/// @param argv
/// @return
void Check_Edge_1(uint16_t CurValue)
{
	CacheSize = sizeof(CacheBuf) / sizeof(CacheBuf[0]);

	// 将最新的数值保存在缓存区中
	if (CacheIndex <= CacheSize - 1)
	{
		CacheBuf[CacheIndex] = CurValue;
		CacheIndex++;

		//
		// BufPrint(CacheBuf, CacheIndex - 1);
	}
	else
	{
		// 所有数据向左移动一位,最后一位保存最新的
		for (uint16_t i = 0; i < CacheSize - 1; i++)
		{
			CacheBuf[i] = CacheBuf[i + 1];
		}

		CacheBuf[CacheSize - 1] = CurValue;

		// BufPrint(CacheBuf, CacheSize - 1);
	}

	// return;

	// 计算差值

	if (CacheIndex <= CacheSize - 1)
	{
		// 数据没有全满,只计算已有数据量的差值
		Diff_Calc(CacheBuf, CacheIndex - 1, &Diff);
	}
	else
	{
		// 缓存区全满,计算所有数据的差值
		Diff_Calc(CacheBuf, CacheSize - 1, &Diff);
	}

	// 查找左侧宽度，右侧宽度，错边量等参数
	printf("lw = %d, rw = %d lo = %d  ro = %d le = %d  re = %d\n",
		   Diff.LeftWidth, Diff.RightWidth,
		   Diff.LeftOffsetCount, Diff.RightOffsetCount,
		   Diff.LeftExceptionCount, Diff.RightExceptionCount);
}

void App1()
{
	printf("Width Measurement\n");

	uint16_t SickMeasurement[100][2] = {0};

	// 准备数据
	PrepareData(SickMeasurement, 100);

	// 测量宽度
	MeasureWidth(SickMeasurement, 100);
}

/// @brief 获取默认数据长度
/// @param
/// @return
uint16_t Get_MLG_2_DefaultDataLen(void)
{
	uint16_t DefaultStrLen = strlen("#001000000000FFFFFFFF**");
	return DefaultStrLen;
}

void MLG_2_Data_Parse(uint8_t *str, uint16_t len)
{
	uint16_t DefaultStrLen = Get_MLG_2_DefaultDataLen();
	int index = FindStrIndex(str, '#');
	printf("index : %d Target : %d\n", index, DefaultStrLen);

	memset(&Diff, 0x00, sizeof(Diff_t));

	// 一整包数据处理，从'#'开始的处理
	for (uint16_t i = index; i < strlen(str) - index;)
	{
		// 数据长度不够，剩下数据无需解析，直接放弃
		if (i + DefaultStrLen > strlen(str))
		{
			return;
		}

		// 只打印23个字符

		// 解析数据
		sscanf((char *)&str[i], "#%04x%04x%04x%04x%04x**",
			   &SickMLG2_Data.SystemTatus,
			   &SickMLG2_Data.QoR,
			   &SickMLG2_Data.OID,
			   &SickMLG2_Data.FBB,
			   &SickMLG2_Data.LBB);

		// printf("%.23s\tS:%d Q:%d OID:%d FBB:%d LBB:%d\n",
		// 	   &str[i],
		// 	   SickMLG2_Data.SystemTatus,
		// 	   SickMLG2_Data.QoR,
		// 	   SickMLG2_Data.OID,
		// 	   SickMLG2_Data.FBB,
		// 	   SickMLG2_Data.LBB);

		i += DefaultStrLen;

		// printf("SystemTatus:%d QoR:%d  OID:%d  FBB:%d  LBB:%d\n",
		// 	   SickMLG2_Data.SystemTatus,
		// 	   SickMLG2_Data.QoR,
		// 	   SickMLG2_Data.OID,
		// 	   SickMLG2_Data.FBB,
		// 	   SickMLG2_Data.LBB);

		// continue;

		Check_Edge_1(SickMLG2_Data.LBB);
	}
}

uint8_t *Gen_MLG2_StrData(uint16_t Count)
{

	uint8_t *str = NULL;
	uint16_t len = Get_MLG_2_DefaultDataLen();

	str = (uint8_t *)malloc(len * Count);
	if (str == NULL)
	{
		printf("malloc error\n");
		return NULL;
	}

	memset(str, 0x00, len * Count);
	for (uint16_t i = 0; i < Count; i++)
	{
		sprintf((char *)&str[i * len], "#%04x%04x%04x%04x%04x**", rand() % 100, rand() % 100, rand() % 10000, 100 + rand() % 10, 100 + rand() % 10);
	}

	return str;
}

/// @brief  解析西克传感器数据
void MLG2_Data_Parse()
{
	/*
		#
		0010 = 16
		0000 = 0
		000E = 14
		0004 = 4
		0011 = 17
		**
	*/

	uint8_t *str = {"#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360066**\
					#00000010002000360066**\
					#00000010002000360066**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360067**\
					#00000010002000360067**\
					#00000010002000360067**\
					#00000010002000360067**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**\
					#00000010002000360063**"};
	MLG_2_Data_Parse(str, strlen(str));
}

int main(int argc, char *argv[])
{

#if 1
	uint8_t *str = Gen_MLG2_StrData(100);
	if (str == NULL)
	{
		return -1;
	}

	MLG_2_Data_Parse(str, strlen(str));

	free(str);
#endif

	return 0;
}